package jp.android_group.attender.android.ui;

/*
 * Copyright (c) 2009, "Japan Android Group Attender Team"
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

import jp.android_group.attender.android.R;
import jp.android_group.attender.android.util.DBHelper;

import org.apache.http.client.HttpResponseException;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.sqlite.SQLiteDatabase;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Toast;

/**
 * 基本アクティビティ
 * 
 */
public abstract class BaseActivity extends Activity {
	public static String LOG_TAG = "BaseActivity";
	public static boolean DEBUG_FLG = true;

	public static final String EXTRA_MODE_OFFLINE = "EXTRA_MODE_OFFLINE";
	static final String SHOW_BARCODE_INTENT = "com.google.zxing.client.android.ENCODE";
	Handler mHandler = new Handler();

	boolean mModeOffline = false;
	volatile SQLiteDatabase mDb = null;

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onCreate(android.os.Bundle)
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		mAlertDialogBuilder = new AlertDialog.Builder(this);

		// オフラインモード判定
		Intent data = getIntent();
		if (data != null && data.hasExtra(EXTRA_MODE_OFFLINE)) {
			mModeOffline = getIntent().getBooleanExtra(EXTRA_MODE_OFFLINE,
					false);
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onResume()
	 */
	@Override
	public void onStart() {
		super.onStart();

		openDatabase();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onPause()
	 */
	@Override
	public void onStop() {
		super.onStop();

		// DBを閉じる
		if (mDb != null && mDb.isOpen()) {
			synchronized (mDb) {
				mDb.releaseReference();
				mDb.close();
			}
		}

	}

	/**
	 * ＤＢ接続を開く
	 */
	final void openDatabase() {
		// DB接続がなければ開く
		if (mDb == null || mDb.isOpen() == false) {
			DBHelper dbHelper = new DBHelper(this, DBHelper.FILE_NAME, null,
					DBHelper.DB_VERSION);
			mDb = dbHelper.getWritableDatabase();
		}
	}

	/**
	 * バーコードスキャナがインストールされているかを判定
	 * 
	 * @return
	 */
	final boolean isBarcodeScannerInstalled() {
		final Intent intent = new Intent(SHOW_BARCODE_INTENT);
		ResolveInfo ri = getPackageManager().resolveActivity(intent,
				PackageManager.MATCH_DEFAULT_ONLY);
		return ri != null;
	}

	AlertDialog.Builder mAlertDialogBuilder = null;

	// 定数：リクエストコード - ＱＲ読み込みの起動
	static final int REQUEST_CODE_QR_SCAN = 0x5532f23a;

	// フラグ ＱＲコード読み込み
	boolean mQrScannerLaunchedFlg = false;

	// QRスキャナのパッケージ
	static final String PACKAGE_NAME_QR_CODE_SCANNER = "com.google.zxing.client.android";

	// QRスキャナのACTION
	static final String ACTION_NAME_QR_CODE_SCANNER = "com.google.zxing.client.android.SCAN";

	/**
	 * ＱＲスキャナ起動
	 */
	final void startQRCodeReader() {

		Intent intent = new Intent(ACTION_NAME_QR_CODE_SCANNER);
		intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
		intent.putExtra("SCAN_MODE", "QR_CODE_MODE");

		try {
			startActivityForResult(intent, REQUEST_CODE_QR_SCAN);
			mQrScannerLaunchedFlg = true;

		} catch (ActivityNotFoundException e) {

			showQRCodeNotFoundAlertDialog();

		}

	}

	/**
	 * QRコードスキャナアプリが見つからないダイアログを表示する
	 */
	final void showQRCodeNotFoundAlertDialog() {

		// インストールされていないダイアログの表示
		AlertDialog dialog = mAlertDialogBuilder.create();
		dialog.setTitle(R.string.qrcode_scanner_not_found_alert_title);
		dialog.setMessage(getResources().getText(
				R.string.qrcode_scanner_not_found_alert));
		dialog.setButton(getResources().getText(R.string.yes),
				new DialogInterface.OnClickListener() {

					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.dismiss();

						// マーケットを開く
						Intent intent = new Intent(Intent.ACTION_VIEW);
						intent.addCategory(Intent.CATEGORY_BROWSABLE);
						intent
								.setData(Uri
										.parse("http://market.android.com/search?q=pname:"
												+ PACKAGE_NAME_QR_CODE_SCANNER));
						startActivity(intent);
						finish();
					}

				});
		dialog.setButton2(getResources().getText(R.string.no),
				new DialogInterface.OnClickListener() {

					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.dismiss();
					}

				});
		dialog.setCancelable(false);
		dialog.show();

	}

	/**
	 * オフラインモードの変更
	 * 
	 * @param mode
	 */
	abstract void changeModeOffline(boolean mode);

	/**
	 * ネットワーク接続の有無を確認
	 * 
	 * @return
	 */
	final boolean checkConnection() {

		ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
		NetworkInfo activeNetworkInfo = cm.getActiveNetworkInfo();
		if (activeNetworkInfo == null)
			return false;

		int netType = activeNetworkInfo.getType();
		if (netType == ConnectivityManager.TYPE_WIFI) {
			return activeNetworkInfo.isConnected();

		} else if (netType == ConnectivityManager.TYPE_MOBILE
				&& activeNetworkInfo.getSubtype() == TelephonyManager.NETWORK_TYPE_UMTS
				&& activeNetworkInfo.isRoaming() == false) {
			return activeNetworkInfo.isConnected();
		} else {
			return false;
		}
	}

	/**
	 * 例外をToastで表示
	 * 
	 * @param e
	 */
	final void showToastException(final Exception e) {
		mHandler.post(new Runnable() {
			@Override
			public void run() {
				if (DEBUG_FLG)
					Log.d(LOG_TAG, e.getLocalizedMessage());
				Toast.makeText(BaseActivity.this, e.getLocalizedMessage(),
						Toast.LENGTH_SHORT).show();
			}
		});
	}

	/**
	 * 例外をToastで表示
	 * 
	 * @param e
	 */
	final void showToastException(final HttpResponseException e) {
		mHandler.post(new Runnable() {
			@Override
			public void run() {
				if (DEBUG_FLG)
					Log.d(LOG_TAG, e.getLocalizedMessage());
				Toast.makeText(BaseActivity.this,
						e.getStatusCode() + " " + e.getLocalizedMessage(),
						Toast.LENGTH_SHORT).show();
			}
		});

	}

	private Dialog mAboutDialog = null;

	/**
	 * 概要ダイアログを表示
	 */
	final void showAboutDialog() {
		if (mAboutDialog == null) {
			mAboutDialog = new Dialog(this);
			mAboutDialog.setTitle(R.string.app_name);
			mAboutDialog.setContentView(R.layout.about);
		}
		mAboutDialog.show();
	}

	private AlertDialog mOfflineAlertDialog = null;

	/**
	 * オフラインの警告ダイアログ表示
	 */
	final void showOfflineAlertDialog() {
		if (mCloseAlertDialog == null) {
			AlertDialog.Builder ab = new AlertDialog.Builder(this);
			mOfflineAlertDialog = ab.create();
			mOfflineAlertDialog.setTitle(R.string.network_unavailable_title);
			mOfflineAlertDialog
					.setMessage(getText(R.string.network_unavailable_message));
			mOfflineAlertDialog.setButton(getText(R.string.ok),
					new Dialog.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							dialog.dismiss();
							changeModeOffline(true);
						}
					});
			mOfflineAlertDialog.setCancelable(false);
		}
		mOfflineAlertDialog.show();
	}

	private AlertDialog mCloseAlertDialog = null;

	/**
	 * 終了確認ダイアログ表示
	 */
	final void showCloseAlertDialog() {
		if (mCloseAlertDialog == null) {
			AlertDialog.Builder ab = new AlertDialog.Builder(this);
			mCloseAlertDialog = ab.create();
			mCloseAlertDialog.setTitle(R.string.exit_confirm_title);
			mCloseAlertDialog
					.setMessage(getText(R.string.exit_confirm_message));
			mCloseAlertDialog.setButton("OK", new Dialog.OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int which) {
					dialog.dismiss();
					finish();
				}
			});
			mCloseAlertDialog.setButton2("Cancel",
					new Dialog.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							dialog.dismiss();
						}
					});
			mCloseAlertDialog.setCancelable(false);
		}
		mCloseAlertDialog.show();
	}

	protected abstract boolean willConfirmWhenClosing();

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onKeyDown(int, android.view.KeyEvent)
	 */
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {

		switch (event.getKeyCode()) {
		case KeyEvent.KEYCODE_BACK:
			if (willConfirmWhenClosing()) {
				showCloseAlertDialog();
				return false;
			} else {
				finish();
			}
		}
		;

		return super.onKeyDown(keyCode, event);
	}
}
